package com.wsc.controller;


import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import com.wsc.frontier.database.DataBaseDetails;
import com.wsc.frontier.database.MasterDB;
 

public class Controller{
	static boolean shutdown = false;
	boolean is_frontier_up = false,is_index_up = false,is_controller_up=false;
	String Controllerlogfile,ControllerMaintenancelogfile,controller_ip,controller_port;
	FIControle fis;
	ControllerConfig cconfig;
	ControllerServer cserver;
	CrawlerControle crawler;
	ControllerClient cclient;
	MasterDB mdb;
	
	public void controllerMaintenance() throws IOException, Exception{
		//looping through maintenance unless shutdown signal sent
		while(!shutdown){
			//checking frontier existence
			Logger.writeLog(ControllerMaintenancelogfile,"Checking frontier existence.....\n");
			int attempt=1;
			int statuscode;
			while(!shutdown){
				//send heart beat to the frontier
				cclient = new ControllerClient();
				cclient.sendRequest(fis.frontier_ip,fis.frontier_port,"heartbeat");
				statuscode = cclient.statuscode;
				attempt++;
				if(statuscode != 200){
					is_frontier_up = false;
					if(attempt == 6){
						Logger.writeLog(ControllerMaintenancelogfile,"Frontier is Down. it is not starting up again check fisstartup logfile for furtherdetails.... number of attempts made :\n"+attempt);
						Logger.writeLog(ControllerMaintenancelogfile,"ControllerMaintenance is going to shutdown......sending shutdown signal to the controller\n");
						shutdown = true;
						break;
					}
					Logger.writeLog(ControllerMaintenancelogfile,"Frontier is Down. trying to up again....attempt \n"+attempt);
					fis.startNode("frontier");
					Thread.sleep(2000);
				}
				else{
					Logger.writeLog(ControllerMaintenancelogfile,"Frontier is ok. it is responding to the heartbeat\n");
					is_frontier_up = true;
				}
			}
			 
			//checking index existence	 
			Logger.writeLog(ControllerMaintenancelogfile,"Checking index existence.....\n");
			attempt=1;
			while(!shutdown){
				//send heart beat to the index
				cclient = new ControllerClient();
				cclient.sendRequest(fis.index_ip,fis.index_port,"heartbeat");
				statuscode = cclient.statuscode;
				attempt++;
				if(statuscode != 200){
					is_index_up = false;
					if(attempt == 6){
						Logger.writeLog(ControllerMaintenancelogfile,"index is Down. it is not starting up again check fisstartup logfile for furtherdetails.... number of attempts made :\n"+(attempt));
						Logger.writeLog(ControllerMaintenancelogfile,"ControllerMaintenance is going to shutdown......sending shutdown signal to the controller\n");
						shutdown = true;
						break;
					}
					Logger.writeLog(ControllerMaintenancelogfile,"index is Down. trying to up again....attempt \n"+attempt);
					fis.startNode("index");
					Thread.sleep(2000);
				}
				else{
					Logger.writeLog(ControllerMaintenancelogfile,"index is ok. it is responding to the heartbeat\n");
					is_index_up = true;
				}
			}
			
			//checking controller server existence
			while(!shutdown){
				attempt = 1;
				cclient = new ControllerClient();
				cclient.sendRequest(ControllerDetails.getControllerServerIP(),ControllerDetails.getControllerServerPort(),"heartbeat");
				statuscode = cclient.statuscode;
				attempt++;
				if(statuscode != 200){
					if(attempt == 6){
						Logger.writeLog(ControllerMaintenancelogfile,"ControllerServer is not responding check ControllerServer logfile for furtherdetails.... number of attempts made :\n"+attempt);
						Logger.writeLog(ControllerMaintenancelogfile,"Checking weather index and frontier are up or not\n");
						cclient = new ControllerClient();
						cclient.sendRequest(fis.index_ip,fis.index_port,"heartbeat");
						statuscode = cclient.statuscode;
						if(statuscode != 200){
							Logger.writeLog(ControllerMaintenancelogfile,"Controller server is not responding and index is down. \n Decided to shutdown controller. \n sending shutdown signal to all avalible nodes\n check logfiles for further details.\n");
							shutdown = true;
							break;
						}
						else{
							Logger.writeLog(ControllerMaintenancelogfile,"Controller server is not responding and index is ok. \n checking frontier existance.\n");
							cclient = new ControllerClient();
							cclient.sendRequest(fis.frontier_ip,fis.frontier_port,"heartbeat");
							statuscode = cclient.statuscode;
							if(statuscode != 200){
								Logger.writeLog(ControllerMaintenancelogfile,"Controller server is not responding and frontier is down. \n Decided to shutdown controller. \n sending shutdown signals to all avalible nodes\n check logfiles for further details.\n");
								shutdown = true;
								break;
							}
							else{
								//starting controller server
								cserver.serverShutdown();
								cserver=null;
								cserver = new ControllerServer();
								Thread t = new Thread(cserver);
								t.start();
								break;
							}
						}
					}
					Logger.writeLog(ControllerMaintenancelogfile,"Controller server is not responding. trying to up again....attempt number \n"+attempt);
				}
				else{
					Logger.writeLog(ControllerMaintenancelogfile,"Controller Server is responding to the heartbeat..");
					break;
				}
			}
			
			//check for the new upcoming crawlers if any then start them up
			if(is_frontier_up && is_index_up && !shutdown){
				crawler.newCrawlerStrartup();
				
				//checking the working of already started crawlers
				while(!shutdown){
					crawler.checkCrawlers(ControllerMaintenancelogfile);
				}
			}
			
			//shutting down all the nodes
			if(shutdown){
				//sending shutdown signals to the crawlers
				Logger.writeLog(ControllerMaintenancelogfile,"all crawlers are trying to shutdown...");
				crawler.shutdownCrawlers();
				Logger.writeLog(ControllerMaintenancelogfile,"all crawlers are shutdown successfully...");
				//sending shutdown signal to the frontier
				Logger.writeLog(ControllerMaintenancelogfile,"frontier is  trying to shutdown...");
				fis.shutdownFrontier();
				Logger.writeLog(ControllerMaintenancelogfile,"frontier is shutdown successfully...");
				//sending shutdown signal to the index
				Logger.writeLog(ControllerMaintenancelogfile,"index is trying to shutdown...");
				fis.shutdownIndex();
				Logger.writeLog(ControllerMaintenancelogfile,"index is shutdown successfully...");
				
				//controller server shutting down
				Logger.writeLog(ControllerMaintenancelogfile,"controller server is trying to shutdown...");
				cserver.serverShutdown();
				String data[] = new String[5];
        		data[0] = "controller";
        		data[1] = ControllerDetails.getControllerServerIP();
        		data[2] = "off";
        		Date dt = new Date();
                DateFormat df = new SimpleDateFormat("yyyy-mm-dd-hh-mm-ss");
        		data[3] = "----";
        		data[4] = df.format(dt);
        		if(mdb.update(DataBaseDetails.getMasterTable(), data,"stoptime")){
        			Logger.writeLog(ControllerMaintenancelogfile, "Controller shutdown details updated successfully...");
        		}
        		else{
        			Logger.writeLog(ControllerMaintenancelogfile, "Unable to update controller shutdown details...");
        		}
				Logger.writeLog(ControllerMaintenancelogfile,"controller server is shutdown successfully...");
				//self shutdown
				Logger.writeLog(ControllerMaintenancelogfile,"controller is trying to shutdown...");
				Logger.writeLog(ControllerMaintenancelogfile,"controller is shutdown successfully...");
				//send shutdown message to the administrator before doing it
				return;
			}
		}
	}
	
	
	
	public void startController() throws IOException, Exception{
		//log file creation
		Controllerlogfile = Logger.logfile("Controller"); //controller log file name
		ControllerMaintenancelogfile = Logger.logfile("ControllerMaintenancelogfile"); //controller maintenance log file name
		
		//creating controller configuration object
		cconfig = new ControllerConfig(); // this class properties aren't decided yet
		Logger.writeLog(Controllerlogfile,"ControllerConfig object created successfully.\n");
				
		/*call necessary controller config methods here
		-----
		------
		------*/
		ControllerDetails.loadXmlFile();
		ControllerDetails.getAllDetails();
		Logger.writeLog(Controllerlogfile,"All details of controller fetched successfully.\n");
		
		DataBaseDetails.loadXmlFile();
		DataBaseDetails.getAllDetails();
		Logger.writeLog(Controllerlogfile,"All details of database fetched successfully.\n");
		
		//creating FIStartup object
		fis = new FIControle();
		Logger.writeLog(Controllerlogfile,"FIStartup object created successfully");
		
		//fistartup log file creation
		fis.logCreation();
		
		//getting frontier and index ip addresses
		Logger.writeLog(Controllerlogfile,"fetching frontier and index ips");
		if(fis.readFINodes()){
			Logger.writeLog(Controllerlogfile,"fetching frontier and index ips done successfully");
		}
		else{
			Logger.writeLog(Controllerlogfile,"there is a problem in fetching frontier and index ips check FIStartuplogfile for futher details");
			System.out.println("Starting of Controller failed check log record for futher details");
			System.exit(1);
			//send this status to the administrator
		}

		//trying to ping index node
		Logger.writeLog(Controllerlogfile,"pinging index node");
		if(fis.ping("index")){
			Logger.writeLog(Controllerlogfile,"pinging index is successful");
		}
		else{
			Logger.writeLog(Controllerlogfile,"pinging index is unsuccessful \n check FIStartuplog record for futher details");
			System.out.println("problem in pinging index node check \n check Controllerlog record for futher details");
			System.exit(2);
		}

		//trying to ping frontier node
		Logger.writeLog(Controllerlogfile,"pinging frontier node");
		if(fis.ping("frontier")){
			Logger.writeLog(Controllerlogfile,"pinging frontier is successful");
		}
		else{
			Logger.writeLog(Controllerlogfile,"pinging frontier is unsuccessful \n check FIStartuplog record for futher details");
			System.out.println("problem in pinging frontier node check \n check Controllerlog record for futher details");
			System.exit(3);
		}
		
		
		//starting controller server
		cserver = new ControllerServer();
		Thread t = new Thread(cserver);//starting controller server as a separate thread
		t.start();
		
		mdb = new MasterDB();
		
		//checking controller server is responding or not
		int attempt = 1;
        while(true){
        	cclient.sendRequest(ControllerDetails.getControllerServerIP(),ControllerDetails.getCrawlerServerPort(),"heartbeat");
        	int code = cclient.statuscode;
        	if(code == 200){
        		Logger.writeLog(Controllerlogfile, "Controller Server respond properly...");
        		is_controller_up = true;
        		if(mdb.getConnection(DataBaseDetails.getDbUrl(),DataBaseDetails.getDatabaseDriver() ,DataBaseDetails.getDatabaseUser(),DataBaseDetails.getDatabasePassword())){
        			String data[] = new String[5];
            		data[0] = "controller";
            		data[1] = ControllerDetails.getControllerServerIP();
            		data[2] = "on";
            		Date dt = new Date();
                    DateFormat df = new SimpleDateFormat("yyyy-mm-dd-hh-mm-ss");
            		data[3] = df.format(dt);
            		data[4] = "----";
            		if(mdb.update(DataBaseDetails.getMasterTable(), data,"starttime")){
            			Logger.writeLog(Controllerlogfile, "Controller start up details updated successfully...");
            		}
            		else{
            			Logger.writeLog(Controllerlogfile, "Unable to update controller start up details...");
            		}
        		}
        		else{
        			Logger.writeLog(Controllerlogfile, "Unable to update controller start up details...");
        		}
        		
        		break;
        	}
        	else{
        		Logger.writeLog(Controllerlogfile, "Controller Server not responding attempt..."+attempt);
        		if(attempt == 6){
        			Logger.writeLog(Controllerlogfile, "Controller Server not responding ...check log file for futher details...\n");
        			Logger.writeLog(Controllerlogfile, "Shutting down the controller...\n");
        			System.exit(6);
        		}
        		Thread.sleep(2000);
        		attempt++;
        	}
        }
		
		//starting index and frontier nodes
		Logger.writeLog(Controllerlogfile,"starting index node\n");
		fis.startNode("index");//ssh failure case is not handled properly
		Logger.writeLog(Controllerlogfile,"starting frontier node\n");
		fis.startNode("frontier");//ssh failure case is not handled properly
		
						
		//this is alternative for ssh failure case
		//checking weather index and frontier servers are up or not
		if(!fis.isFrontierServerup()){//return true if frontier server is up
			Logger.writeLog(Controllerlogfile,"Frontier is not responding. \n check FIStartuplog record for futher details");
			System.out.println("unable to start frontier \n check Controllerlog record for futher details");
			System.exit(4);
		}
		else{
			Logger.writeLog(Controllerlogfile,"Frontier is ok. it is responding to the heartbeat.\n");
			is_frontier_up = true;
		}
		
		if(!fis.isIndexServerup()){//return true if index server is up
			Logger.writeLog(Controllerlogfile,"index is not responding. \n check FIStartuplog record for futher details");
			System.out.println("unable to start index \n check Controllerlog record for futher details");
			System.exit(4);
		}
		else{
			Logger.writeLog(Controllerlogfile,"index is ok. it is responding to the heartbeat.\n");
			is_index_up = true;
		}

		//creating Crawler Controller object
		crawler = new CrawlerControle();
		Logger.writeLog(Controllerlogfile,"ControllerStartup object created successfully");
		
		//crawlerControle log file creation
		crawler.logCreation();
		
		//setting crawler port
		crawler.setPort(ControllerDetails.getCrawlerServerPort());
		
		//getting crawler ips
		Logger.writeLog(Controllerlogfile,"fetching crawler ips");
		if(crawler.getCrawlerIps()){
			Logger.writeLog(Controllerlogfile,"fetching of crawler ips done successfully");
		}
		else{
			Logger.writeLog(Controllerlogfile,"there is a problem in fetching crawler ips check FIStartuplogfile for futher details");
			System.out.println("Starting of Controller failed check log record for futher details");
			System.exit(5);
			//send this status to the administrator
		}
		
		//pinging of all crawler nodes
		Logger.writeLog(Controllerlogfile,"pinging of crawler nodes\n");
		crawler.crawlerPinging();
			
		//starting all crawler nodes
		Logger.writeLog(Controllerlogfile,"starting  crawler nodes\n");
		crawler.startCrawlerNodes();
		Logger.writeLog(Controllerlogfile,"crawlernodes started successfully\n");
	}
	
	
	public static void main(String...ss) throws IOException, Exception{
		//creation of controller object
		Controller con = new Controller();
		
		//starting controller
		con.startController();
				
		//controller maintenance
		con.controllerMaintenance();
	}
}
